package org.example.CLI;

import org.example.command.*;
import org.example.exception.InvalidCommandException;
import org.example.model.HTMLDocument;
import org.example.service.spellcheck.LanguageToolSpellChecker;

import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 解析命令行参数并封装成命令。
 */
public class CommandParser {

    // 将被''包裹的字符串提取出来, 并将字符串中的转义字符还原
    private static String extractStringContent(String str) {
        return str
                .replaceAll("^'", "")
                .replaceAll("'$", "")
                .replace("\\\\", "\\")
                .replace("\\'", "'");
    }

    public static Command parse(HTMLDocument htmlDocument, CommandInvoker commandInvoker, String commandline)
            throws InvalidCommandException {

        String insertRegex = "^insert\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s*(.*)?$";
        String appendRegex = "^append\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s*(.*)?$";
        String editIdRegex = "^edit-id\\s+(\\S+)\\s+(\\S+)$";
        String editTextRegex = "^edit-text\\s+(\\S+)\\s*(.*)?$";
        String deleteRegex = "^delete\\s+(\\S+)$";
        String printIndentRegex = "^print-indent\\s*(\\d+)?$";
        String printTreeRegex = "^print-tree$";
        String spellCheckRegex = "^spell-check$";
        String readRegex = "^read\\s+(\\S+)$";
        String saveRegex = "^save\\s+(\\S+)$";
        String initRegex = "^init$";
        String undoRegex = "^undo$";
        String redoRegex = "^redo$";

        if (commandline.matches(insertRegex)) {
            Matcher m = Pattern.compile(insertRegex).matcher(commandline);
            if (m.matches()) {
                String tagName = m.group(1);
                String idValue = m.group(2);
                String parentElementId = m.group(3);
                String textContent = m.group(4) != null ? extractStringContent(m.group(4)) : "";
                return InsertElementCommand.create(htmlDocument, tagName, idValue, parentElementId, textContent);
            } else {
                throw new InvalidCommandException("Invalid insert command: " + commandline);
            }
        } else if (commandline.matches(appendRegex)) {
            Matcher m = Pattern.compile(appendRegex).matcher(commandline);
            if (m.matches()) {
                String tagName = m.group(1);
                String idValue = m.group(2);
                String parentElementId = m.group(3);
                String textContent = m.group(4) != null ? extractStringContent(m.group(4)) : "";
                return AppendElementCommand.create(htmlDocument, tagName, idValue, parentElementId, textContent);
            } else {
                throw new InvalidCommandException("Invalid append command: " + commandline);
            }
        } else if (commandline.matches(editIdRegex)) {
            Matcher m = Pattern.compile(editIdRegex).matcher(commandline);
            if (m.matches()) {
                String oldId = m.group(1);
                String newId = m.group(2);
                return EditElementIdCommand.create(htmlDocument, oldId, newId);
            } else {
                throw new InvalidCommandException("Invalid edit-id command: " + commandline);
            }
        } else if (commandline.matches(editTextRegex)) {
            Matcher m = Pattern.compile(editTextRegex).matcher(commandline);
            if (m.matches()) {
                String elementId = m.group(1);
                String newTextContent = m.group(2) != null ? extractStringContent(m.group(2)) : "";
                return EditElementTextCommand.create(htmlDocument, elementId, newTextContent);
            } else {
                throw new InvalidCommandException("Invalid edit-text command: " + commandline);
            }
        } else if (commandline.matches(deleteRegex)) {
            Matcher m = Pattern.compile(deleteRegex).matcher(commandline);
            if (m.matches()) {
                String elementId = m.group(1);
                return DeleteElementCommand.create(htmlDocument, elementId);
            } else {
                throw new InvalidCommandException("Invalid delete command: " + commandline);
            }
        } else if (commandline.matches(printIndentRegex)) {
            Matcher m = Pattern.compile(printIndentRegex).matcher(commandline);
            if (m.matches()) {
                String indentStr = m.group(1);
                int indent = indentStr != null ? Integer.parseInt(indentStr) : 2; // 默认为 2
                return PrintIndentCommand.create(htmlDocument, indent);
            } else {
                throw new InvalidCommandException("Invalid print-indent command: " + commandline);
            }
        } else if (commandline.matches(printTreeRegex)) {
            return new PrintTreeCommand(htmlDocument);
        } else if (commandline.matches(spellCheckRegex)) {
            return SpellCheckCommand.create(htmlDocument,new LanguageToolSpellChecker());
        } else if (commandline.matches(readRegex)) {
            Matcher m = Pattern.compile(readRegex).matcher(commandline);
            if (m.matches()) {
                String filepath = m.group(1);
                return ReadCommand.create(htmlDocument, filepath);
            } else {
                throw new InvalidCommandException("Invalid read command: " + commandline);
            }
        } else if (commandline.matches(saveRegex)) {
            Matcher m = Pattern.compile(saveRegex).matcher(commandline);
            if (m.matches()) {
                String filepath = m.group(1);
                return SaveCommand.create(htmlDocument, filepath);
            } else {
                throw new InvalidCommandException("Invalid save command: " + commandline);
            }
        } else if (commandline.matches(initRegex)) {
            return InitCommand.create(htmlDocument);
        } else if (commandline.matches(undoRegex)) {
            return new UndoCommand(commandInvoker);
        } else if (commandline.matches(redoRegex)) {
            return new RedoCommand(commandInvoker);
        }
        throw new InvalidCommandException("Invalid command: " + commandline);
    }
}
